package com.powerband.apiheartrate.tools

import java.util.*
import kotlin.experimental.and
import kotlin.experimental.xor

object FBKSpliceBle {
    fun bytesToHexString(byteArray: ByteArray?): String {
        if (byteArray == null) return ""
        val stringBuffer = StringBuffer(byteArray.size)
        for (i in byteArray.indices) {
            val stringTemp = Integer.toHexString(
                0xFF and byteArray[i]
                    .toInt()
            )
            if (stringTemp.length < 2) stringBuffer.append(0)
            stringBuffer.append(stringTemp.uppercase(Locale.getDefault()))
        }
        return stringBuffer.toString()
    }

    fun hexStringToBytes(hex: String?): ByteArray {
        if (hex == null) return ByteArray(0)
        val byteList = ByteArray(hex.length / 2)
        for (i in byteList.indices) {
            val index = i * 2
            val v = hex.substring(index, index + 2).toInt(16)
            byteList[i] = v.toByte()
        }
        return byteList
    }

    fun stringToAscii(value: String): ByteArray {
        return value.toByteArray()
    }

    fun utf8ToUnicode(text: String): ByteArray {
        val utfBytes = text.toCharArray()
        var unicodeBytes = ""
        for (i in utfBytes.indices) {
            var hexB = Integer.toHexString(utfBytes[i].code)
            if (hexB.length <= 2) hexB = "00$hexB"
            unicodeBytes = unicodeBytes + hexB
        }
        return hexStringToBytes(unicodeBytes)
    }

    fun getIntBit(dataNumber: Int, startBit: Int, endBit: Int): Int {
        if (startBit < 0 || startBit > 15) return 0
        if (endBit < 0 || endBit > 15) return 0
        return if (startBit > endBit) 0 else dataNumber and 65535 shr 15 - endBit shr startBit
    }

    fun compareByte(byte1: ByteArray, byte2: ByteArray): Boolean {
        var isEqual = true
        if (byte1.size != byte2.size) isEqual = false
        for (i in byte1.indices) {
            if (byte1[i] != byte2[i]) {
                isEqual = false
                break
            }
        }
        return isEqual
    }

    fun byteOverflow(value: Int, bitNumber: Int): Int {
        var hiNum = 0
        var resultNum = value
        if (bitNumber == 4) {
            val tww = 255
            hiNum = (tww shl 24) + (tww shl 16) + (tww shl 8) + tww
        } else if (bitNumber == 2) {
            hiNum = 65535
        }
        if (value < 0) resultNum = value + hiNum
        return resultNum
    }

    fun bleMacAddress(bleByte: ByteArray?): Map<String, Any>? {
        if (bleByte == null) return null
        if (bleByte.size < 8) return null
        var macString = ""
        for (i in 2..7) {
            val macHex = Integer.toHexString(
                0xFF and bleByte[i]
                    .toInt()
            )
            macString = if (macHex.length == 1) {
                macString + "0" + macHex
            } else {
                macString + macHex
            }
            if (i != 7) macString = "$macString:"
        }
        return mapOf("macAddress" to macString)
    }

    @OptIn(ExperimentalUnsignedTypes::class)
    fun decodeManufacturerData(orgBroadcastData: ByteArray?): UByteArray? {
        orgBroadcastData?.let {
            val maxLen = it.size
            var index = 0
            while (index < maxLen) {
                var len = it[index].toInt()
                if (len <= 0 || len + 1 >= maxLen) {
                    index += 1
                    continue
                }
                index += 1
                val adType = it[index]
                if (adType != 0xFF.toByte()) {
                    index += len
                    continue
                }
                return it.sliceArray((index + 1) until index + len).toUByteArray()
            }
        }
        return null
    }

    fun encryptionData(valueData: ByteArray, key: Int): ByteArray {
        val encryptionByte = ByteArray(valueData.size)
        for (i in valueData.indices) {
            val value: Byte = valueData[i] and 0xFF as Byte
            encryptionByte[i] = (value xor key.toByte()).toByte()
        }
        return encryptionByte
    }

    fun compareUuid(bleUuid: UUID, uuidString: String): Boolean {
        if (bleUuid == UUID.fromString(uuidString)) return true
        var bleUuidString = bleUuid.toString().uppercase(Locale.getDefault())
        bleUuidString = bleUuidString.substring(4, 8)
        var compareString = uuidString.uppercase(Locale.getDefault())
        compareString = compareString.substring(4, 8)
        return bleUuidString == compareString
    }
}